import ntplib
import os, datetime
import binascii
import hashlib
import hmac
import sys
import urllib.parse
import urllib.request
import time
import random
import requests
# encoding=utf8

def sign(secretKey, signStr, signMethod):
    '''
    该方法主要是实现腾讯云的签名功能
    :param secretKey: 用户的secretKey
    :param signStr: 传递进来字符串，加密时需要使用
    :param signMethod: 加密方法
    :return:
    '''
    if sys.version_info[0] > 2:
        signStr = signStr.encode("utf-8")
        secretKey = secretKey.encode("utf-8")

    # 根据参数中的signMethod来选择加密方式
    if signMethod == 'HmacSHA256':
        digestmod = hashlib.sha256
    elif signMethod == 'HmacSHA1':
        digestmod = hashlib.sha1

    # 完成加密，生成加密后的数据
    hashed = hmac.new(secretKey, signStr, digestmod)
    base64 = binascii.b2a_base64(hashed.digest())[:-1]

    if sys.version_info[0] > 2:
        base64 = base64.decode()

    return base64

def dictToStr(dictData):
    '''
    本方法主要是将Dict转为List并且拼接成字符串
    :param dictData:
    :return: 拼接好的字符串
    '''
    tempList = []
    for eveKey, eveValue in dictData.items():
        tempList.append(str(eveKey) + "=" + str(eveValue))
    return "&".join(tempList)


# 用户必须准备好的secretId和secretKey
# 可以在 https://console.cloud.tencent.com/capi 获取
secretId = "AKIDEPh3EQWT4gBc5Sp7FIAtseCj6IG1oqiX"
secretKey = "iCSW9k55zgAQTNr8C4mSyGMFvVIKFG6l"

# 在此处定义一些必须的内容
timeData = str(int(time.time())) # 时间戳
nonceData = int(random.random()*10000) # Nonce，官网给的信息：随机正整数，与 Timestamp 联合起来， 用于防止重放攻击
actionData = "DescribeZones" # Action一般是操作名称
uriData = "cvm.tencentcloudapi.com" # uri，请参考官网
signMethod="HmacSHA256" # 加密方法
requestMethod = "GET" # 请求方法，在签名时会遇到，如果签名时使用的是GET，那么在请求时也请使用GET
regionData = "ap-beijing" # 区域选择
versionData = '2017-03-12' # 版本选择

# 签名时需要的字典
# 首先对所有请求参数按参数名做字典序升序排列，所谓字典序升序排列，
# 直观上就如同在字典中排列单词一样排序，按照字母表或数字表里递增
# 顺序的排列次序，即先考虑第一个“字母”，在相同的情况下考虑第二
# 个“字母”，依此类推。
signDictData = {
    'Action' : actionData,
    'Nonce' : nonceData,
    'Region' : regionData,
    'SecretId' : secretId,
    'SignatureMethod':signMethod,
    'Timestamp' : int(timeData),
    'Version':versionData ,
}

# 获得拼接的字符串，用于签名
# 此步骤生成请求字符串。 将把上一步排序好的请求参数格式化成“参数名称”=“参数值”的形式，如对Action参数，
# 其参数名称为"Action"，参数值为"DescribeInstances"，因此格式化后就为Action=DescribeInstances。
# 注意：“参数值”为原始值而非url编码后的值。
# 然后将格式化后的各个参数用"&"拼接在一起，最终生成请求字符串。
# 此步骤生成签名原文字符串。 签名原文字符串由以下几个参数构成:
# 1) 请求方法: 支持 POST 和 GET 方式，这里使用 GET 请求，注意方法为全大写。
# 2) 请求主机:查看实例列表(DescribeInstances)的请求域名为：cvm.tencentcloudapi.com。实际的请求域名根据接口所属模块的不同而不同，详见各接口说明。
# 3) 请求路径: 当前版本云API的请求路径固定为 / 。 4) 请求字符串: 即上一步生成的请求字符串。
# 签名原文串的拼接规则为:
#   请求方法 + 请求主机 +请求路径 + ? + 请求字符串
requestStr = "%s%s%s%s%s"%(requestMethod,uriData,"/","?",dictToStr(signDictData))

# 调用签名方法，同时将结果进行url编码，官方文档描述如下：
# 生成的签名串并不能直接作为请求参数，需要对其进行 URL 编码。 注意：如果用户的请求方法是GET，则对所有请求参
# 数值均需要做URL编码。 如上一步生成的签名串为 EliP9YW3pW28FpsEdkXt/+WcGeI= ，最终得到的签名串请求参数(Signature)
# 为： EliP9YW3pW28FpsEdkXt%2f%2bWcGeI%3d ，它将用于生成最终的请求URL。
signData = urllib.parse.quote(sign(secretKey,requestStr,signMethod))

# 上述操作是实现签名，下面即进行请求
# 先建立请求参数, 此处参数只在签名时多了一个Signature
actionArgs = signDictData
actionArgs["Signature"] = signData

# 根据uri构建请求的url
requestUrl = "https://%s/?"%(uriData)
# 将请求的url和参数进行拼接
requestUrlWithArgs = requestUrl + dictToStr(actionArgs)

# 获得response
responseData = urllib.request.urlopen(requestUrlWithArgs).read().decode("utf-8")

print(responseData)

# 获得到的结果形式：
#  "Response": {
#         "TotalCount": *,
#         "InstanceSet": [
#             {
#                ******
#          ],
#          "RequestId": "***********"
#    }
#}

hosts = ['0.cn.pool.ntp.org', '1.cn.pool.ntp.org', '2.cn.pool.ntp.org', '3.cn.pool.ntp.org']
hosts = ['ntp.aliyun.com', 'ntp1.aliyun.com', 'ntp2.aliyun.com', 'ntp3.aliyun.com', 'ntp4.aliyun.com',
         'ntp5.aliyun.com']


def ntp_client():
    # hosts = ['0.cn.pool.ntp.org','1.cn.pool.ntp.org','2.cn.pool.ntp.org','3.cn.pool.ntp.org']
    hosts = ['ntp.aliyun.com', 'ntp1.aliyun.com', 'ntp2.aliyun.com', 'ntp3.aliyun.com', 'ntp4.aliyun.com',
             'ntp5.aliyun.com']
    # 创建实例，NTPClient()是一个类
    t = ntplib.NTPClient()
    for host in hosts:
        try:
            # ntp server可以填写主机和域名，建议用域名
            # 缺省端口为ntp， 版本为2， 超时为5s
            # 作用：查询 NTP 服务器，并返回对象
            r = t.request(host, port='ntp', version=4, timeout=5)
            # r = t.request(host ,version=4, timeout=5)
            if r:
                break
        except Exception as e:
            pass
    # 显示的是时间戳
    t = r.tx_time
    # print(t)
    # 使用datetime模块,格式化：x年x月x日 时:分:秒.毫秒
    _date, _time = str(datetime.datetime.fromtimestamp(t))[:22].split(' ')
    print("调整前时间是：", datetime.datetime.now())
    os.system('date {} && time {}'.format(_date, _time))
    print("调整后时间是：", datetime.datetime.now())


def get_web_now_timea(time_format='YYYY-MM-DD HH:mm:ss.SSSSSS'):
    """
    获取网络时间，返回时间格式：2019-12-13 11:39:48.398
    :param time_format:控制返回字符串的格式，默认为：'YYYY-MM-DD HH:mm:ss.SSS'
    :return:
    """
    import arrow as ar
    import requests as req
    # print('\n=========    获取网络时间   =========')

    try:
        res = req.get('http://console.cloud.tencent.com/').headers['Date']
        # res = req.get('https://www.hao123.com/').headers['Date']
        time_diff = ar.get(res[4:-4], 'DD MMM YYYY HH:mm:ss') - ar.now().floor('second')
        web_now_time = (ar.now() + time_diff).format(time_format)

        # print('web_now_time={}'.format(web_now_time))

        return web_now_time
    except BaseException as e:
        print('获取网络时间出错，出错原因：{}'.format(e))
        return -1


def get_web_now_timeaa(time_format='YYYY-MM-DD HH:mm:ss.SSS'):
    """
    获取网络时间，返回时间格式：2019-12-13 11:39:48.398
    :param time_format:控制返回字符串的格式，默认为：'YYYY-MM-DD HH:mm:ss.SSS'
    :return:
    """
    import arrow as ar
    import requests as req
    # print('\n=========    获取网络时间   =========')

    try:
        res = req.get('http://console.cloud.tencent.com/').headers['Date']
        # res = req.get('https://www.hao123.com/').headers['Date']
        time_diff = ar.get(res[4:-4], 'DD MMM YYYY HH:mm:ss') - ar.now().floor('second')
        web_now_time = (ar.now() + time_diff).format(time_format)

        # print('web_now_time={}'.format(web_now_time))

        return web_now_time
    except BaseException as e:
        print('获取网络时间出错，出错原因：{}'.format(e))
        return -1


def zf13stamp(ax):
    ata = datetime.datetime.strptime(ax[:-4], "%Y-%m-%d %H:%M:%S")
    print(ata)
    att = get_time13(ata)
    atx = att + int(ax[-3:])
    return atx


def zf16stamp(ax):
    ata = datetime.datetime.strptime(ax[:-7], "%Y-%m-%d %H:%M:%S")
    print(ata)
    att = get_time16(ata)
    atx = att + int(ax[-6:])
    return atx


def get_time13(datetime_obj):
    import datetime, time
    # 生成13时间戳   eg:1557842280000
    datetime_str = datetime.datetime.strftime(datetime_obj, '%Y-%m-%d %H:%M:00')
    datetime_obj = datetime.datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:00')
    # print(datetime_obj)
    # 10位，时间点相当于从1.1开始的当年时间编号
    date_stamp = str(int(time.mktime(datetime_obj.timetuple())))
    # 3位，微秒
    data_microsecond = str("%06d" % datetime_obj.microsecond)[0:3]
    date_stamp = date_stamp + data_microsecond
    return int(date_stamp)


def get_time16(datetime_obj):
    import datetime, time
    # 生成16时间戳   eg:1557842280000
    datetime_str = datetime.datetime.strftime(datetime_obj, '%Y-%m-%d %H:%M:00')
    datetime_obj = datetime.datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:00')
    # print(datetime_obj)
    # 10位，时间点相当于从1.1开始的当年时间编号
    date_stamp = str(int(time.mktime(datetime_obj.timetuple())))
    # 3位，微秒
    data_microsecond = str("%06d" % datetime_obj.microsecond)[0:6]
    date_stamp = date_stamp + data_microsecond
    return int(date_stamp)


def request2getjob_id(signature_str, app_id, filepath, sortkeydict):
    """

    :param signature_str: j加密后的签名
    :param app_id:   appid=1314615815 ,在控制台“云API密钥”获得
    :param filepath:  本地音频文件路径
    :param sortkeydict: 访问语音API需要的参数列表，已经过字典排序
    :return: job_id 任务id，用于获取语音结果。
    """
    print('签名字符', urllib.parse.quote(signature_str))
    body = ''
    with open(filepath, 'rb') as f:
        body = f.read()
    header = {
        "Host": "cvm.tencentcloudapi.com",
        "Content-Type": "application/octet-stream",
        "Authorization": signature_str,
        "Content-Length": str(len(body)),
    }

    url = "cvm.tencentcloudapi.com" + str(1314615815) + '?' + urllib.parse.urlencode(sortkeydict)
    print(url)
    response = requests.post(url, data=body, headers=header)
    if response.status_code == 200:
        print("上传识别音频文件成功")
        result = eval(str(response.content))
        # 任务ID
        job_id = result.get("requestid")
        return job_id
    else:
        print("失败")
        # 根据返回的code去腾讯的文档中心来查看是哪一步出错了
        # https://cloud.tencent.com/document/product/441/6201
        print(response.content)


if __name__ == '__main__':
    # ntp_client()
    aa = zf16stamp(get_web_now_timea())
    print(aa)
    aa = zf13stamp(get_web_now_timeaa())
    print(aa)
    os.system("pause")